package com.stox.navigator.ui.swing.widget;

import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JToolBar.Separator;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.tree.DefaultMutableTreeNode;

import com.stox.core.ui.swing.util.ThrowableReporter;
import com.stox.core.ui.swing.wrapper.JButton;
import com.stox.core.ui.swing.wrapper.JPanel;
import com.stox.core.ui.swing.wrapper.JTextField;
import com.stox.core.ui.swing.wrapper.JToggleButton;
import com.stox.core.ui.swing.wrapper.JTree;
import com.stox.core.util.StringUtil;
import com.stox.design.Callback;
import com.stox.design.Holder;
import com.stox.resources.i18n.MessageSource;

public class AutoNavigationPanel extends JPanel {
	private static final long serialVersionUID = 5453635256775678850L;

	private Holder<JTree> holder;
	private Class<?> clazz;
	private Callback<DefaultMutableTreeNode, Object> callback;
	
	private JButton previousButton = new JButton(null,MessageSource.getMessage("Previous"), "go_left.png", KeyEvent.VK_P);
	private JToggleButton autoToggleButton = new JToggleButton(MessageSource.getMessage("Auto"), false);
	private JTextField delayTextField = new JTextField(MessageSource.getMessage("Delay")+" 2 "+MessageSource.getMessage("Seconds"));
	private JButton nextButton = new JButton(null,MessageSource.getMessage("Next"), "go_right.png", KeyEvent.VK_N);
	private boolean reverseDirection = false;
	private boolean auto = false;
	private Runnable runnable = new Runnable(){
		@Override
		public void run() {
			executeCallback();
		}
	};
	private Timer timer;
	private TimerTask timerTask;
	

	public AutoNavigationPanel(Holder<JTree> holder, 
			Class<?> clazz, 
			Callback<DefaultMutableTreeNode, Object> callback) {
		this.holder = holder;
		this.clazz = clazz;
		this.callback = callback;
		afterPropertiesSet();
	}
	
	public void afterPropertiesSet(){
		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		add(previousButton);
		add(new Separator());
		add(autoToggleButton);
		add(new Separator());
		add(delayTextField);
		delayTextField.setHorizontalAlignment(JTextField.CENTER);
		delayTextField.setMargin(new Insets(0,0,0,0));
		delayTextField.setEnabled(!auto);
		
		add(new Separator());
		add(nextButton);
		setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
		
		previousButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				reverseDirection = true;
				if(!auto){
					executeCallback();
				}
			}
		});
		
		autoToggleButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				auto = autoToggleButton.isSelected();
				delayTextField.setEnabled(!auto);
				
				if(auto){
					startAutoNavigation();
				}else{
					cancelAutoNavigation();
				}
			}
		});
		
		nextButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				reverseDirection = false;
				if(!auto){
					executeCallback();
				}
			}
		});
	}
	
	
	
	@Override
	public Dimension getPreferredSize() {
		Dimension dimension = super.getPreferredSize();
		dimension.height = 30;
		return dimension;
	}
	
	@Override
	public Dimension getSize() {
		Dimension dimension = super.getSize();
		dimension.height = 30;
		return dimension;
	}
	
	
	private void startAutoNavigation(){
		timer = new Timer();
		timerTask = new TimerTask(){
			@Override
			public void run() {
				SwingUtilities.invokeLater(runnable);
			}
		};
		String text = delayTextField.getText();
		long delay = 2000;
		if(StringUtil.hasText(text)){
			try{
				delay = new Double(Double.parseDouble(text)*1000).longValue();
			}catch(NumberFormatException nfe){
				ThrowableReporter.report(MessageSource.getMessage("Please.enter.a.numeric.value.in.delay.field"));
				return;
			}
			
		}
		timer.schedule(timerTask, 0, delay);
	}
	
	private void cancelAutoNavigation(){
		timer.cancel();
	}

	private void executeCallback(){
		DefaultMutableTreeNode node = getTargetSelectionNode();
		if(node != null){
			JTree tree = holder.get();
			tree.selectAndShow(node);
			callback.execute(node);
		}else{
			autoToggleButton.doClick();
		}
	}
	
	private DefaultMutableTreeNode getTargetSelectionNode(){
		JTree tree = holder.get();
		DefaultMutableTreeNode node = null;
		if(tree.getSelectionPath() == null){
			node = (DefaultMutableTreeNode)tree.getModel().getRoot();
			if(reverseDirection){
				node = node.getLastLeaf();
			}
		}else{
			node = (DefaultMutableTreeNode)tree.getSelectionPath().getLastPathComponent();
		}

		do{
			node = reverseDirection? node.getPreviousNode():node.getNextNode();
		}while(node != null && !clazz.isAssignableFrom(node.getUserObject().getClass()));
		return node;
	}
}